package com.doeis.core;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Array;
import java.util.Enumeration;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.doeis.common.Constant;
import com.doeis.core.db.Page;
import com.doeis.manage.bean.User;
import com.doeis.tools.BeanUtils;
import com.doeis.tools.HashKit;
import com.doeis.tools.StringHelper;

public abstract class SuperAction extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private static final Log log = LogFactory.getLog(SuperAction.class);

	private HttpServletRequest request = null;
	private HttpServletResponse response = null;

	/* 所有跳转页面的路径 */
	protected final String PAGE_PATH = "/WEB-INF/page";

	public static final int PAGE_SIZE = 10; // 默认每页显示多个行
	private static final int WIDTH = 80, HEIGHT = 26;
	private static final String[] strArr = { "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "M", "N", "P", "Q",
			"R", "S", "T", "U", "V", "W", "X", "Y" };

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		this.request = req;
		this.response = resp;
		doPost(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String url = request.getRequestURI();
		request.setAttribute(Constant.LAST_PAGE_URL, url);
		String urls[] = url.split("/");
		if (urls.length == 0) {
			return;
		}
		String methodName = null;
		if (urls.length == 2) {
			methodName = "index";
		} else {
			methodName = urls[2];
		}
		try {
			this.doRequest(methodName, request, response);
		} catch (Exception e) {
			throw new ServletException(e);
		}
	}

	protected abstract void doRequest(String methodName, HttpServletRequest request, HttpServletResponse response) throws Exception;

	public HttpServletRequest getRequest() {
		return request;
	}

	public HttpServletResponse getResponse() {
		return response;
	}

	public HttpSession getSession() {
		return getRequest().getSession();
	}

	protected <T> T getParam(Class<T> paramClazz, String paramName) {
		try {
			HttpServletRequest request = getRequest();
			String value = request.getParameter(paramName);
			return getValue(paramClazz, value);
		} catch (Exception e) {
			log.error("获取参数，并转成对象出错", e);
		}
		return null;
	}

	protected <T> T[] getParams(Class<T> paramClazz, String paramName) {
		try {
			HttpServletRequest request = getRequest();
			String[] values = request.getParameterValues(paramName);
			Object[] array = (Object[]) Array.newInstance(paramClazz, 0);
			Object obj = null;
			if (values != null) {
				for (String value : values) {
					obj = getValue(paramClazz, value);
					array = ArrayUtils.add(array, obj);
				}
			}
			return (T[]) array;
		} catch (Exception e) {
			log.error("获取参数数组，并转成对象出错", e);
		}
		return null;
	}

	private <T> T getValue(Class<T> paramClazz, String value) {
		if (StringUtils.isNotBlank(value)) {
			value = value.trim();
			if (String.class.equals(paramClazz)) {
				return (T) value;
			}
			if (BeanUtils.isPrimitiveOrEntity(paramClazz))
				return (T) BeanUtils.primitiveObj(value, paramClazz);
			if (BeanUtils.isOutPrimitiveEntity(paramClazz)) {
				return (T) BeanUtils.outPrimitiveObj(value, paramClazz);
			}
		} else if ((paramClazz.isInstance(Boolean.TYPE)) || ("boolean".equals(paramClazz.getName()))) {
			return (T) Boolean.FALSE;
		}

		return null;
	}

	protected <T> T paramsToForm(Class<T> formClass) {
		Object formBean = null;
		try {
			HttpServletRequest request = getRequest();
			Enumeration<String> names = request.getParameterNames();
			formBean = formClass.newInstance();
			String paramName = null;
			String value = null;
			String[] values = null;

			while (names.hasMoreElements()) {
				paramName = (String) names.nextElement();
				try {
					if (paramName.endsWith("[]")) {
						values = request.getParameterValues(paramName);
						String field = paramName.replaceAll("\\[\\]", "");
						BeanUtils.setProperty(formBean, field, values);
					} else {
						value = request.getParameter(paramName);
						if (value != null) {
							value = value.trim();
							BeanUtils.setProperty(formBean, paramName, value);
						}
					}
				} catch (Exception e) {
					log.warn("Error setting property '" + paramName + "' with value '" + value + "'", e);
				}
			}
		} catch (Exception e) {
			log.error("从参数生成Form对象时异常", e);
		}

		return (T) formBean;
	}

	public void setServletRequest(HttpServletRequest request) {
		this.request = request;
	}

	public void sendData(String content) {
		writerData(content);
	}

	public void sendJsonObject(Object obj) {
		String content = JSON.toJSONString(obj);
		sendData(content);
	}

	public void sendJsonArray(Object obj) {
		String content = JSONArray.toJSONString(obj);
		sendData(content);
	}

	protected void initPageData(Page page, String listAttributeName) {
		HttpServletRequest request = getRequest();
		request.setAttribute("_page", page.getPage());
		request.setAttribute("_total_page", Integer.valueOf(page.getTotalPages()));
		request.setAttribute("_total_recode", Integer.valueOf(page.getTotalRecords()));

		request.setAttribute(listAttributeName, page.getResults());
	}

	private void writerData(String data) {
		try {
			if (StringUtils.isBlank(data))
				return;
			HttpServletResponse response = getResponse();
			response.setContentType("text/html;charset=UTF-8");
			PrintWriter writer = response.getWriter();
			writer.write(data);
			writer.flush();
			log.debug("send data:" + data);
		} catch (Exception e) {
			log.error(e);
		}
	}

	public Page getPage() {
		return (Page) paramsToForm(Page.class);
	}

	/**
	 * 检查session是否失效
	 * 
	 * @Title: checkSession
	 * @data:2016-4-16下午3:16:18
	 * @author:wxy
	 * @return
	 * 
	 */
	protected boolean checkSession(HttpServletRequest request, HttpServletResponse response) {
		User user = (User) request.getSession().getAttribute(Constant.SYSTEM_CURRENT_USER);
		if (user == null) {
			return false;
		}
		return true;
	}

	protected User getLoginUser(HttpServletRequest request) {
		User user = (User) request.getSession().getAttribute(Constant.SYSTEM_CURRENT_USER);
		return user;
	}

	/**
	 * Get cookie value by cookie name.
	 */
	public String getCookie(HttpServletRequest request, String name) {
		Cookie cookie = getCookieObject(request, name);
		return cookie != null ? cookie.getValue() : "";
	}

	public void addCookie(HttpServletResponse response, Cookie cookie) {
		if (cookie != null) {
			response.addCookie(cookie);
		}
	}

	/**
	 * Get cookie object by cookie name.
	 */
	public Cookie getCookieObject(HttpServletRequest request, String name) {
		Cookie[] cookies = request.getCookies();
		if (cookies != null)
			for (Cookie cookie : cookies)
				if (cookie.getName().equals(name))
					return cookie;
		return null;
	}

	public void captcha(HttpServletResponse response, String randomCodeKey) {
		BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
		String vCode = drawGraphic(image);
		vCode = HashKit.md5(vCode.toLowerCase());
		Cookie cookie = new Cookie(randomCodeKey, vCode);
		cookie.setMaxAge(-1);
		cookie.setPath("/");
		response.addCookie(cookie);
		response.setHeader("Pragma", "no-cache");
		response.setHeader("Cache-Control", "no-cache");
		response.setDateHeader("Expires", 0);
		response.setContentType("image/jpeg");

		ServletOutputStream sos = null;
		try {
			sos = response.getOutputStream();
			ImageIO.write(image, "jpeg", sos);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (sos != null)
				try {
					sos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}
	}

	private String drawGraphic(BufferedImage image) {
		// 获取图形上下文
		Graphics g = image.createGraphics();
		// 生成随机类
		Random random = new Random();
		// 设定背景色
		g.setColor(getRandColor(200, 250));
		g.fillRect(0, 0, WIDTH, HEIGHT);
		// 设定字体
		g.setFont(new Font("Times New Roman", Font.PLAIN, 18));

		// 随机产生155条干扰线，使图象中的认证码不易被其它程序探测到
		g.setColor(getRandColor(160, 200));
		for (int i = 0; i < 155; i++) {
			int x = random.nextInt(WIDTH);
			int y = random.nextInt(HEIGHT);
			int xl = random.nextInt(12);
			int yl = random.nextInt(12);
			g.drawLine(x, y, x + xl, y + yl);
		}

		// 取随机产生的认证码(4位数字)
		String sRand = "";
		for (int i = 0; i < 4; i++) {
			String rand = String.valueOf(strArr[random.nextInt(strArr.length)]);
			sRand += rand;
			// 将认证码显示到图象中
			g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
			// 调用函数出来的颜色相同，可能是因为种子太接近，所以只能直接生成
			g.drawString(rand, 16 * i + 11, 19);
		}

		// 图象生效
		g.dispose();

		return sRand;
	}

	/*
	 * 给定范围获得随机颜色
	 */
	private Color getRandColor(int fc, int bc) {
		Random random = new Random();
		if (fc > 255)
			fc = 255;
		if (bc > 255)
			bc = 255;
		int r = fc + random.nextInt(bc - fc);
		int g = fc + random.nextInt(bc - fc);
		int b = fc + random.nextInt(bc - fc);
		return new Color(r, g, b);
	}

	public boolean validate(HttpServletRequest request, String inputRandomCode) {
		if (StringHelper.isNull(inputRandomCode))
			return false;
		inputRandomCode = HashKit.md5(inputRandomCode.toLowerCase());
		return inputRandomCode.equalsIgnoreCase(getCookie(request, "randomCodeKey"));
	}

	public void sendData(String content, HttpServletResponse response) {
		writerData(content, response);
	}

	public void sendJsonObject(Object obj, HttpServletResponse response) {
		String content = JSON.toJSONString(obj);
		sendData(content, response);
	}

	public void sendJsonArray(Object obj, HttpServletResponse response) {
		String content = JSONArray.toJSONString(obj);
		sendData(content, response);
	}

	private void writerData(String data, HttpServletResponse response) {
		if (StringHelper.isNull(data))
			return;
		try {
			response.setContentType("text/html;charset=UTF-8");
			PrintWriter writer = response.getWriter();
			writer.write(data);
			writer.flush();
			log.debug((new StringBuilder("send data:")).append(data).toString());
		} catch (Exception e) {
			log.error(e);
		}
		return;
	}

	/**
	 * 添加消息信息
	 * 
	 * @param request
	 * @param msg
	 * @author wxy 2016年3月19日星期六中国标准时间下午2:45:11
	 */
	public void addActionMessage(HttpServletRequest request, String msg) {
		request.setAttribute("actionMessage", msg);
	}

	/**
	 * 跳转到错误页面
	 * 
	 * @param request
	 * @param response
	 * @author wxy 2016年3月19日星期六中国标准时间下午3:36:09
	 */
	public void errorPage(String name, HttpServletRequest request, HttpServletResponse response) {
		try {
			request.getRequestDispatcher(PAGE_PATH + "/common/" + name + ".jsp").forward(request, response);
			return;
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 跳转到管理页面
	 * 
	 * @Title: toIndex
	 * @data:2014-1-6上午09:40:37
	 * @author:xieyan
	 *
	 * @param request
	 * @param response
	 */
	public void toPage(String methodName, String path, HttpServletRequest request, HttpServletResponse response) {
		try {
			request.getRequestDispatcher(PAGE_PATH + "/" + path + "/" + methodName + ".jsp").forward(request, response);
			return;
		} catch (ServletException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public int getUserid(HttpServletRequest request) {
		User user = (User) request.getSession().getAttribute(Constant.SYSTEM_CURRENT_USER);
		return user != null ? user.getId() : -1;
	}
}